#pragma once
#include "geometry.h"
#include <string>
#include <stdexcept>
#include <vector>
#include <map>
#include "meshType.h"

class Entity
{
	public:
        std::string name;
        std::string meshName;
        std::string materialName;
	
	public:
		Entity(std::string n, std::string mN, std::string matN) : name(n), meshName(mN), materialName(matN) {};
};

class SceneNode
{
	public:
	std::vector<SceneNode*> childs;
	std::string entityName;
	MeshUtils::Vector3 position;
	MeshUtils::Quaternion orientation;

	public:
		inline ~SceneNode() {for(std::vector<SceneNode*>::iterator itS = childs.begin() ; itS != childs.end() ; itS++) delete (*itS);};
		inline void linkEntity(string name) {entityName = name;};
		inline SceneNode& createChild(void) { SceneNode* nw = new SceneNode(); childs.push_back(nw); return *nw;};

		inline std::string getEntityName(void) {return entityName;};
		inline MeshUtils::Vector3 getPosition(void) {return position;};
		inline MeshUtils::Quaternion getOrientation(void) {return orientation;};

		inline void setPostion(MeshUtils::Vector3& p) {position = p;};
		inline void setOrientation(MeshUtils::Quaternion& q) {orientation = q;};
};

class Material
{
    public:
        unsigned char R, G, B, A;
        Material() : R(0), G(0), B(0), A(255) {};
};

class SceneManager
{
	SceneNode* root;
	std::map<std::string, Entity*> entities;
	std::map<std::string, Material> materials;

	public:
		inline SceneManager(void) : root(new SceneNode()) {};
		inline void addMaterial(const Material m, string name) {materials[name] = m;};
		inline Material getMaterial(string name)
        {
                return materials[name];
        };
		inline SceneNode& getRoot(void) {return *root;};
		inline Entity& createEntity(string eName, string mshName, string matName) {Entity* ent = new Entity(eName, mshName, matName) ; entities[eName] = ent; return *ent;};
		inline Entity& getEntity(string name) {
			Entity* ent = entities[name];
			if(ent)
				return *ent;
			else
				throw std::runtime_error("no entity associated with that name : " + name);
			};
};
